﻿using Deployment.Data.Deploy.Steps.Tasks;
using System;
using System.Collections.Generic;
using System.Xml.Serialization;

namespace Deployment.Data.Deploy.Steps
{
    [XmlRoot("Step")]
    [Serializable()]
    public class Step : NotifyPropertyChanged
    {
        private int _stepId;
        private string _description;
        private bool _ProcessTasksInParallel = false;
        private bool _isContentOk = false;

        private ExecutionStatus _executionStatus = ExecutionStatus.Idle;

        private ObservableSortedList<AbstractTask> _Tasks = new ObservableSortedList<AbstractTask>(4, new TaskComparer());

        public Step()
            : base()
        {
            this.PropertyChanged += Step_PropertyChanged;
        }

        void Step_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (!e.PropertyName.Equals("isContentOk"))
                OnPropertyChanged("isContentOk");
        }

        [XmlAttribute]
        public int Sequence
        {
            get { return _stepId; }
            set
            {
                if (_stepId != value)
                {
                    _stepId = value;
                    OnPropertyChanged("StepId");
                }
            }
        }

        [XmlAttribute]
        public string Description
        {
            get { return _description; }
            set
            {
                if (value != _description)
                {
                    _description = value;
                    OnPropertyChanged("Description");
                }
            }
        }

        /// <summary>
        /// ProcessTasksInParallel property will allow certain tasks to execute at the same time.
        /// 
        /// NOTE: Tasks can override this setting 
        /// </summary>
        [XmlAttribute]
        public bool ProcessTasksInParallel
        {
            get { return _ProcessTasksInParallel; }
            set
            {
                if (value != _ProcessTasksInParallel)
                {
                    _ProcessTasksInParallel = value;
                    OnPropertyChanged("ProcessTasksInParallel");
                }
                
            }
        }

        [XmlArray("Tasks")]
        [XmlArrayItem("Task", Type = typeof(TaskXmlSerializer<AbstractTask>))]
        public ObservableSortedList<AbstractTask> Tasks
        {
            get { return _Tasks; }
        }

        public void AddTask(AbstractTask newTask)
        {
            this._Tasks.Add(newTask);
        }

        public bool RemoveTask(AbstractTask task)
        {
            return this._Tasks.Remove(task);
        }

        [XmlIgnore]
        public bool isContentOk
        {
            get { return !string.IsNullOrEmpty(this.Description); }
        }

        [XmlIgnore]
        public ExecutionStatus ExecutionStatus
        {
            get { return _executionStatus; }
            private set
            {
                if (_executionStatus != value)
                {
                    _executionStatus = value;
                    OnPropertyChanged("ExecutionStatus");
                }
            }
        }

        private class TaskComparer : IComparer<AbstractTask>
        {

            public int Compare(AbstractTask x, AbstractTask y)
            {
                if (x == null && y == null)
                    return 0;
                if (x == null && y != null)
                    return -1;
                if (x != null && y == null)
                    return 1;

                return x.Id - y.Id;
            }
        }

        public object Clone()
        {
            throw new NotImplementedException();
        }
    }
}
